#include "Socket.h"
#include "socket_include.h"
#include "SocketHandler.h"

//#include <fcntl.h>
#ifdef _WIN32
WSAInitializer Socket::m_winsock_init;
#endif


Socket::Socket(ISocketHandler& h) : 
	m_handler(h),
	m_socket(INVALID_SOCKET),
	m_b_enable_ssl(false),
	m_b_ssl(false),
	m_host(0),
	m_port(0) 
{}


Socket::~Socket() {
	m_handler.Remove(this);
	if (m_socket != INVALID_SOCKET) {
		Close();
	}
}


SOCKET Socket::CreateSocket(int af,int type, const std::string & protocol)
{
	struct protoent *p = NULL;
	SOCKET s;

	m_socket_protocol = protocol;

	if (protocol.size())
	{
		p = getprotobyname( protocol.c_str() );
		if (!p)
		{
			return INVALID_SOCKET;
		}
	}
	int protno = p ? p -> p_proto : 0;

	if ((s = socket(af, type, protno)) == INVALID_SOCKET)
	{
		return INVALID_SOCKET;
	}
	Attach(s);
	return s;
}


ISocketHandler& Socket::Handler() const {
	return m_handler;
}


bool Socket::SetNonblocking(bool bNb)
{
	SetNonblocking(bNb, m_socket);
}


bool Socket::SetNonblocking(bool bNb, SOCKET s)
{
#ifdef _WIN32
	unsigned long l = bNb ? 1 : 0;
	int n = ioctlsocket(s, FIONBIO, &l);
	if (n != 0)
	{
		return false;
	}
	return true;
#else
	if (bNb)
	{
		if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
		{
			return false;
		}
	}
	else
	{
		if (fcntl(s, F_SETFL, 0) == -1)
		{
			return false;
		}
	}
	return true;
#endif
}


int Socket::Close() {
	if (m_socket == -1) {// this could happen
		return 0;
	}
	int n;
	if ((n = closesocket(m_socket)) == -1) {
		// failed...
	}
}


bool Socket::IsSSL()
{
	return m_b_enable_ssl;
}


void Socket::EnableSSL(bool x)
{
	m_b_enable_ssl = x;
}


bool Socket::IsSSLNegotiate()
{
	return m_b_ssl;
}


void Socket::SetSSLNegotiate(bool x)
{
	m_b_ssl = x;
}
